//
// Created by Win on 2016/12/29.
//

#include <stdio.h>
#include <frbyte_buffer.h>
#include <frrmi.h>
#include <frsoap_parse.h>
#include <frhessian.h>
#include "serialize_hessian2.h"
#include "http_bodydata_deal.h"
#include "yongyou_parse.h"

FR_STATIC int frgzip_detect(char *p_tcp_body, unsigned int ui_tcp_body_len);
FR_STATIC int http_rmi_detect(char *p_tcp_body, unsigned int ui_tcp_body_len);
FR_STATIC int frjson_detect(char *p_tcp_body, unsigned int ui_tcp_body_len);
FR_STATIC int frhtml_detect(char *p_tcp_body, unsigned int ui_tcp_body_len);
FR_STATIC int frjava_serialized_detect(char *p_tcp_body, unsigned int ui_tcp_body_len);
FR_STATIC int frjava_serialized_deal(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, int i_use_request, char *p_prefix);
FR_STATIC int frhessian_detect(char *p_tcp_body, unsigned int ui_tcp_body_len);

extern int g_i_redetect;
extern int g_i_yongyou;
extern int g_i_rmi;
extern int g_i_hessian;
extern int g_i_report_non_xml_json_html;

/*!
 * \brief http body体判断
 *
 * \arg p_comm_session          HTTP相关信息
 *      p_tcp_body              数据内容
 *      ui_tcp_body_len         数据长度
 *
 * \return                      FR_SUCC:成功
 *                              FR_FAIL:失败
 */
int http_bodydata_type_detect(Http_comm_session *p_comm_session, char *p_tcp_body, unsigned int ui_tcp_body_len)
{
    unsigned int ui_header_buff_len = 0;
    
    if(p_comm_session == NULL)
        return FR_FAIL;
    
    //不需要的数据 直接丢弃
    if(p_comm_session->i_flag_need == 2)
        return FR_SUCC;
    
    //是否保存数据未知的情况下  content-type 不存在情况下
    if(p_comm_session->i_flag_need == 0)
    {
        
        //判断是否为 RMI 或者 是gzip数据内容二次判断
        //判断RMI
        if(g_i_rmi)
        {
            if(http_rmi_detect(p_tcp_body, ui_tcp_body_len) == HTTP_BODYTYPE_MATCHED)
            {
                p_comm_session->i_flag_need = 1;
                if (g_i_yongyou)
                    p_comm_session->i_flag_data_type = HTTP_YONGYOU_DATA;
                else
                    p_comm_session->i_flag_data_type = HTTP_RMI_DATA;  //rmi
                
                return FR_SUCC;
            }
    
            if(frjava_serialized_detect(p_tcp_body, ui_tcp_body_len) == HTTP_BODYTYPE_MATCHED)
            {
                p_comm_session->i_flag_need = 1;
                p_comm_session->i_flag_data_type = HTTP_JAVA_SERIALIZED;
                return FR_SUCC;
            }
        }
        
        //判断GZIP
        if(g_i_redetect)
        {
            if(frgzip_detect(p_tcp_body, ui_tcp_body_len) == HTTP_BODYTYPE_MATCHED)
            {
                p_comm_session->i_flag_need = 1;
                p_comm_session->i_flag_gzip = 1;
                p_comm_session->i_flag_data_type = HTTP_GZIP_DATA;
                
                return FR_SUCC;
            }
        }
        
        if(g_i_hessian)
        {
            if(frhessian_detect(p_tcp_body, ui_tcp_body_len) == HTTP_BODYTYPE_MATCHED)
            {
                p_comm_session->i_flag_need = 1;
                p_comm_session->i_flag_data_type = HTTP_HESSIAN_DATA;
                return FR_SUCC;
            }
        }
        
        //判断是否为 json xml 等
        while (ui_header_buff_len < ui_tcp_body_len)
        {
            if (p_tcp_body[ui_header_buff_len] == '\r' || p_tcp_body[ui_header_buff_len] == '\n' ||
                p_tcp_body[ui_header_buff_len] == '\t' || p_tcp_body[ui_header_buff_len] == ' ')
            {
                ui_header_buff_len++;
                continue;
            }
            
            p_tcp_body += ui_header_buff_len;
            ui_tcp_body_len -= ui_header_buff_len;
            
            if (frxml_detect(p_tcp_body, ui_tcp_body_len) == FR_SUCC)
            {
                p_comm_session->i_flag_data_type = HTTP_XML_DATA;
                return FR_SUCC;
            }
            else if (frjson_detect(p_tcp_body, ui_tcp_body_len) == HTTP_BODYTYPE_MATCHED)
            {
                p_comm_session->i_flag_data_type = HTTP_JSON_DATA;
                return FR_SUCC;
            }
            else if (frhtml_detect(p_tcp_body, ui_tcp_body_len) == HTTP_BODYTYPE_MATCHED)            //判断HTML
            {
                p_comm_session->i_flag_need = 2;
                p_comm_session->i_flag_data_type = HTTP_OTHERS_DATA;
                return FR_SUCC;
            }
            else
            {
                if (g_i_report_non_xml_json_html)
                    p_comm_session->i_flag_need = 1;
                else
                    p_comm_session->i_flag_need = 2;
                p_comm_session->i_flag_data_type = HTTP_OTHERS_DATA;
                return FR_SUCC;
            }
        }
    }
    
    //content-type   text/*
    if(p_comm_session->i_flag_data_type == HTTP_TEXT_DATA)  // text/*  获取可能的json xml数据
    {
        
        while (ui_header_buff_len < ui_tcp_body_len)
        {
            if (p_tcp_body[ui_header_buff_len] == '\r' || p_tcp_body[ui_header_buff_len] == '\n' ||
                p_tcp_body[ui_header_buff_len] == '\t' || p_tcp_body[ui_header_buff_len] == ' ')
            {
                ui_header_buff_len++;
                continue;
            }
            
            p_tcp_body += ui_header_buff_len;
            ui_tcp_body_len -= ui_header_buff_len;
            
            if (frxml_detect(p_tcp_body, ui_tcp_body_len) == FR_SUCC)
            {
                p_comm_session->i_flag_data_type = HTTP_XML_DATA;
                return FR_SUCC;
            }
            else if (frjson_detect(p_tcp_body, ui_tcp_body_len) == HTTP_BODYTYPE_MATCHED)
            {
                p_comm_session->i_flag_data_type = HTTP_JSON_DATA;
                return FR_SUCC;
            }
            else if (frhtml_detect(p_tcp_body, ui_tcp_body_len) == HTTP_BODYTYPE_MATCHED)            //判断HTML
            {
                p_comm_session->i_flag_need = 2;
                p_comm_session->i_flag_data_type = HTTP_OTHERS_DATA;
                return FR_SUCC;
            }
            else
            {
                if(g_i_report_non_xml_json_html)
                    p_comm_session->i_flag_need = 1;
                else
                    p_comm_session->i_flag_need = 2;
                p_comm_session->i_flag_data_type = HTTP_OTHERS_DATA;
                return FR_SUCC;
            }
        }
    }
    
    return FR_SUCC;
}


/*!
 * \brief           HTTP 之上的协议解码
 *
 * \arg             p_packet    (数据内容)
 *                  p_comm_session （http 信息）
 *                  p_st_body_data  （上报数据收集链表）
 *                  i_use_request    （是否使用request）
 *
 * \return          HTTP_EXTEND_DONE_SUCC:解码完成
 *                  HTTP_EXTEND_DONE_FAIL:解码失败
 *                  HTTP_EXTEND_UNDONE:不是扩展协议
 */
int frhttp_extend_bodydata_deal(Frbyte_Packet *p_packet, Http_comm_session *p_comm_session, Frreport_body_data *p_st_body_data, int i_use_request)
{
    int i_ret = 0;
    Frbyte_Packet *p_packet_decode = NULL;
    int i_deep = 0;
    
    if(p_packet == NULL || p_comm_session == NULL || p_st_body_data == NULL)
        return HTTP_EXTEND_DONE_FAIL;
    
    
    switch (p_comm_session->i_flag_data_type)
    {
        case HTTP_RMI_DATA:
            readRmi(p_packet, p_st_body_data, i_use_request, (char *)"http.rmi");
            bytebuff_free(&p_comm_session->p_st_data);
            return HTTP_EXTEND_DONE_SUCC;
    
        case HTTP_YONGYOU_DATA:
            p_packet_decode = bytebuff_creat();
            parseYongYou(p_packet, p_packet_decode);
            
            i_ret = readStreamHeader(p_packet_decode);
            if(i_ret == FR_FAIL)
            {
                bytebuff_free(&p_comm_session->p_st_data);
                bytebuff_free(&p_packet_decode);
            
            }
        
            i_ret = yongyou_readObject(p_packet_decode, p_st_body_data, i_use_request, &i_deep, (char *)"http.rmi");
            if(i_ret == FR_FAIL)
            {
                bytebuff_free(&p_comm_session->p_st_data);
                bytebuff_free(&p_packet_decode);
            
            }
    
            //readRmi(p_packet_decode, p_st_body_data, FR_YES, (char *)"http.rmi");
            bytebuff_free(&p_comm_session->p_st_data);
            bytebuff_free(&p_packet_decode);
            return HTTP_EXTEND_DONE_SUCC;
    
        case HTTP_JAVA_SERIALIZED:
            frjava_serialized_deal(p_packet, p_st_body_data, i_use_request, (char *)"http.rmi");
            bytebuff_free(&p_comm_session->p_st_data);
            return HTTP_EXTEND_DONE_SUCC;
    
        case HTTP_HESSIAN_DATA:
            if(i_use_request == FR_YES)
                frhessian_req_read(p_packet, p_st_body_data, (char *)"request.http.hessian");
            else
                frhessian2_resp_read(p_packet, p_st_body_data, (char *)"response.http.hessian2");
                
            return HTTP_EXTEND_DONE_SUCC;
    
        default:
            break;
            
    }
    
    
    return HTTP_EXTEND_UNDONE;
    
}

/*!
 * \brief           判断HTTP BODY CHUNKED传输的时候 是否有协议扩展
 *
 * \arg             p_comm_session （http 信息）
 *
 * \return          FR_YES:有协议扩展
 *                  FR_NO:没有协议扩展
 *
 */
int frhttp_body_extended(Http_comm_session *p_comm_session)
{
    if(p_comm_session == NULL)
        return FR_NO;
    

    
    switch (p_comm_session->i_flag_data_type)
    {
        case HTTP_RMI_DATA:
            return FR_YES;
    
        case HTTP_YONGYOU_DATA:
            return FR_YES;
    
        case HTTP_JAVA_SERIALIZED:
            return FR_YES;
    
        case HTTP_HESSIAN_DATA:
            return FR_YES;
        
        default:
            return FR_NO;
    }
    
}


/*!
 * \brief 判断HTTP 体是否为gzip
 *
 * \arg p_tcp_bdoy          数据包内容
 *      ui_tcp_body_len     数据包长度
 *      i_flag_chunked      chunk传输
 *
 * \return                  HTTP_BODYTYPE_MATCHED:符合
 *                          HTTP_BODYTYPE_UNMATCHED：不符合
 *                          HTTP_BODYTYPE_UNKNOW：不能确定
 *
 */

FR_STATIC int frjava_serialized_deal(Frbyte_Packet *p_st_data, Frreport_body_data *p_st_body_data, int i_use_request, char *p_prefix)
{
    int i_ret = 0;
    int i_deep = 0;
    
    if(p_st_data == NULL || p_st_body_data == NULL || p_prefix == NULL)
        return FR_FAIL;
    
    i_ret = readStreamHeader(p_st_data);
    if(i_ret == FR_FAIL)
        return FR_FAIL;
    
    i_ret = readObject(p_st_data, p_st_body_data, i_use_request, &i_deep, p_prefix);
    if(i_ret == FR_FAIL)
        return FR_FAIL;
    
    return i_ret;
}



/*!
 * \brief 判断HTTP 体是否为HTML
 *
 * \arg p_tcp_bdoy          数据包内容
 *      ui_tcp_body_len     数据包长度
 *      i_flag_chunked      chunk传输
 *
 * \return                  HTTP_BODYTYPE_MATCHED:符合
 *                          HTTP_BODYTYPE_UNMATCHED：不符合
 *                          HTTP_BODYTYPE_UNKNOW：不能确定
 *
 */
FR_STATIC int frhtml_detect(char *p_tcp_body, unsigned int ui_tcp_body_len)
{
    if(p_tcp_body == NULL || ui_tcp_body_len < 6)
        return HTTP_BODYTYPE_UNMATCHED;
    
    //  判断是否为html
    if(ui_tcp_body_len > 6)
    {
        if(strncasecmp(p_tcp_body, "<html>", 6) == 0
           || strncasecmp(p_tcp_body, "<html ", 6) == 0)
            return HTTP_BODYTYPE_MATCHED;
        
    }
    
    if(ui_tcp_body_len > 15)
    {
        if(strncasecmp(p_tcp_body, "<!DOCTYPE html>", 15) == 0
           || strncasecmp(p_tcp_body, "<!DOCTYPE html ", 15) == 0)
            return HTTP_BODYTYPE_MATCHED;
    }
    
    return HTTP_BODYTYPE_UNMATCHED;
}

/*!
 * \brief 判断HTTP 体是否为json
 *
 * \arg p_tcp_bdoy          数据包内容
 *      ui_tcp_body_len     数据包长度
 *      i_flag_chunked      chunk传输
 *
 * \return                  HTTP_BODYTYPE_MATCHED:符合
 *                          HTTP_BODYTYPE_UNMATCHED：不符合
 *                          HTTP_BODYTYPE_UNKNOW：不能确定
 *
 */
FR_STATIC int frjson_detect(char *p_tcp_body, unsigned int ui_tcp_body_len)
{
    if(p_tcp_body == NULL || ui_tcp_body_len < 1)
        return HTTP_BODYTYPE_UNMATCHED;
    
    //判断是否是以 '{' '[' 开头
    if(p_tcp_body[0] == '{' || p_tcp_body[0] == '[')
        return HTTP_BODYTYPE_MATCHED;
    
    return HTTP_BODYTYPE_UNMATCHED;
}

/*!
 * \brief 判断HTTP 体是否为rmi
 *
 * \arg p_tcp_bdoy          数据包内容
 *      ui_tcp_body_len     数据包长度
 *      i_flag_chunked      chunk传输
 *
 * \return                  HTTP_BODYTYPE_MATCHED:符合
 *                          HTTP_BODYTYPE_UNMATCHED：不符合
 *                          HTTP_BODYTYPE_UNKNOW：不能确定
 *
 */
FR_STATIC int http_rmi_detect(char *p_tcp_body, unsigned int ui_tcp_body_len)
{
    if(p_tcp_body == NULL || ui_tcp_body_len < 8)
        return HTTP_BODYTYPE_UNMATCHED;
    
    if(memcmp(p_tcp_body + 4, "\x72\x71\x89", 3) == 0)
        return HTTP_BODYTYPE_MATCHED;
    
    return HTTP_BODYTYPE_UNMATCHED;
}

/*!
 * \brief 判断HTTP 体是否为x-java-serialized-object
 *
 * \arg p_tcp_bdoy          数据包内容
 *      ui_tcp_body_len     数据包长度
 *
 * \return                  HTTP_BODYTYPE_MATCHED:符合
 *                          HTTP_BODYTYPE_UNMATCHED：不符合
 *                          HTTP_BODYTYPE_UNKNOW：不能确定
 *
 */
FR_STATIC int frjava_serialized_detect(char *p_tcp_body, unsigned int ui_tcp_body_len)
{
    if(p_tcp_body == NULL || ui_tcp_body_len < 4)
        return HTTP_BODYTYPE_UNMATCHED;
    
    if(memcmp(p_tcp_body, "\xac\xed\x00\x05", 4) == 0)
        return HTTP_BODYTYPE_MATCHED;
    
    return HTTP_BODYTYPE_UNMATCHED;
}

/*!
 * \brief 判断HTTP 体是否为gzip
 *
 * \arg p_tcp_bdoy          数据包内容
 *      ui_tcp_body_len     数据包长度
 *
 * \return                  HTTP_BODYTYPE_MATCHED:符合
 *                          HTTP_BODYTYPE_UNMATCHED：不符合
 *                          HTTP_BODYTYPE_UNKNOW：不能确定
 *
 */
FR_STATIC int frgzip_detect(char *p_tcp_body, unsigned int ui_tcp_body_len)
{
    if(p_tcp_body == NULL || ui_tcp_body_len < 10)
        return HTTP_BODYTYPE_UNMATCHED;
    
    if(memcmp(p_tcp_body, "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00", 10) == 0)
        return HTTP_BODYTYPE_MATCHED;
    
    return HTTP_BODYTYPE_UNMATCHED;
}


/*!
 * \brief 判断HTTP 体是否为hessian call
 *
 * \arg p_tcp_bdoy          数据包内容
 *      ui_tcp_body_len     数据包长度
 *
 * \return                  HTTP_BODYTYPE_MATCHED:符合
 *                          HTTP_BODYTYPE_UNMATCHED：不符合
 *                          HTTP_BODYTYPE_UNKNOW：不能确定
 *
 */
FR_STATIC int frhessian_call_detect(char *p_tcp_body, unsigned int ui_tcp_body_len)
{
    if(p_tcp_body == NULL || ui_tcp_body_len < 4)
        return HTTP_BODYTYPE_UNMATCHED;
    
    //\x63 2byte version
    if(p_tcp_body[0] != '\x63' || p_tcp_body[1] > '\x09')
        return HTTP_BODYTYPE_UNMATCHED;
    
    if(memcmp(p_tcp_body + 2, "\x00\x6d", 2) != 0)
        return HTTP_BODYTYPE_UNMATCHED;
    
    return HTTP_BODYTYPE_MATCHED;
}


/*!
 * \brief 判断HTTP 体是否为hessian2 reply
 *
 * \arg p_tcp_bdoy          数据包内容
 *      ui_tcp_body_len     数据包长度
 *
 * \return                  HTTP_BODYTYPE_MATCHED:符合
 *                          HTTP_BODYTYPE_UNMATCHED：不符合
 *                          HTTP_BODYTYPE_UNKNOW：不能确定
 *
 */
FR_STATIC int frhessian2_reply_detect(char *p_tcp_body, unsigned int ui_tcp_body_len)
{
    if(p_tcp_body == NULL || ui_tcp_body_len < 4)
        return HTTP_BODYTYPE_UNMATCHED;
    
    //\x72 1byte version + 0 +
    if(p_tcp_body[0] != '\x48' || p_tcp_body[1] > '\x09')
        return HTTP_BODYTYPE_UNMATCHED;
    
    if(memcmp(p_tcp_body + 2, "\x00\x52", 2) != 0)
        return HTTP_BODYTYPE_UNMATCHED;
    
    return HTTP_BODYTYPE_MATCHED;
}

/*!
 * \brief 判断HTTP 体是否为hessian 或者hessian2
 *
 * \arg p_tcp_bdoy          数据包内容
 *      ui_tcp_body_len     数据包长度
 *
 * \return                  HTTP_BODYTYPE_MATCHED:符合
 *                          HTTP_BODYTYPE_UNMATCHED：不符合
 *                          HTTP_BODYTYPE_UNKNOW：不能确定
 *
 */
FR_STATIC int frhessian_detect(char *p_tcp_body, unsigned int ui_tcp_body_len)
{
    if(frhessian_call_detect(p_tcp_body, ui_tcp_body_len) == HTTP_BODYTYPE_MATCHED)
        return HTTP_BODYTYPE_MATCHED;
    
    if(frhessian2_reply_detect(p_tcp_body, ui_tcp_body_len) == HTTP_BODYTYPE_MATCHED)
        return HTTP_BODYTYPE_MATCHED;
    
    return HTTP_BODYTYPE_UNMATCHED;
}
